package main

import (
	"context"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	//演示使用http.Server进行优雅关机
	router := gin.Default()
	router.GET("/", func(c *gin.Context) {
		time.Sleep(5 * time.Second)
		c.String(http.StatusOK, "5秒后正常返回结果")
	})

	srv := &http.Server{
		Addr:    ":10001",
		Handler: router,
	}

	go func() {
		// 由于ListenAndServe是阻塞操作，为了后续代码执行，这里通过新goroutine开启
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("ListenAndServe失败: %s\n", err)
		}
	}()

	//等待中断信号发生后，通过10秒的超时控制关闭
	quit := make(chan os.Signal, 1) // 创建一个接收信号的通道
	// kill 默认会发送 syscall.SIGTERM 信号
	// kill -2 发送 syscall.SIGINT 信号，我们常用的Ctrl+C就是触发系统SIGINT信号
	// kill -9 发送 syscall.SIGKILL 信号，但是不能被捕获，所以不需要添加它
	// signal.Notify会把收到的 syscall.SIGINT或syscall.SIGTERM 信号转发给quit
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	// 阻塞 当接收到任意两种信号之一时 往下执行
	<-quit
	log.Println("关闭服务器中 ...")
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	//若当前无未处理完的请求，则直接关闭
	//否者等待请求处理完或10秒后依然没有处理完则自动超时强制结束
	//在shutdown执行之前未处理完的请求若均完成，则会提前结束
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("关闭服务器失败: ", err)
	}
	log.Println("服务器关闭")
}
